package com.uvnos4j.matilda.system.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.uvnos4j.matilda.commons.dto.PageParam;
import com.uvnos4j.matilda.commons.dto.QueryParam;
import com.uvnos4j.matilda.commons.exception.ServiceException;
import com.uvnos4j.matilda.commons.utils.MpUtil;
import com.uvnos4j.matilda.system.domain.SysRole;
import com.uvnos4j.matilda.system.domain.SysRoleAcl;
import com.uvnos4j.matilda.system.domain.SysUserRole;
import com.uvnos4j.matilda.system.error.SystemError;
import com.uvnos4j.matilda.system.mapper.SysRoleAclMapper;
import com.uvnos4j.matilda.system.mapper.SysRoleMapper;
import com.uvnos4j.matilda.system.mapper.SysUserRoleMapper;
import com.uvnos4j.matilda.system.service.SysRoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;

/**
 * 角色 Service 实现
 * <p>
 * Description:角色 Service 实现
 * </p>
 *
 * @author Guo.wl
 * @version v1.0.0
 * @see com.uvnos4j.matilda.system.service.impl
 * @since 2020-08-31 23:25:49
 */
@Service
@Transactional(readOnly = true)
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements SysRoleService {
    @Autowired
    private SysUserRoleMapper sysUserRoleMapper;

    @Autowired
    private SysRoleAclMapper sysRoleAclMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean save(SysRole sysRole) {
        if (hasSameRole(sysRole.getEnname(), null)) {
            throw new ServiceException(SystemError.ROLE_ENNAME_REPORT);
        }
        sysRole.setCreateTime(DateTime.now());
        return baseMapper.insert(sysRole) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateById(SysRole sysRole) {
        if (hasSameRole(sysRole.getEnname(), sysRole.getId())) {
            throw new ServiceException(SystemError.ROLE_ENNAME_REPORT);
        }
        return baseMapper.updateById(sysRole) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeByIds(Collection<? extends Serializable> roleIdList) {
        // 删除角色用户关系
        LambdaQueryWrapper<SysUserRole> lqw = new LambdaQueryWrapper<>();
        lqw.in(SysUserRole::getRoleId, roleIdList);
        sysUserRoleMapper.delete(lqw);
        // 删除角色权限关系
        LambdaQueryWrapper<SysRoleAcl> lqw2 = new LambdaQueryWrapper<>();
        lqw2.in(SysRoleAcl::getRoleId, roleIdList);
        sysRoleAclMapper.delete(lqw2);

        // 删除角色
        int affectedRows = baseMapper.deleteBatchIds(roleIdList);
        return affectedRows > 0;
    }

    @Override
    public IPage<SysRole> findPage(QueryParam param, PageParam pageParam, String orderBy) {
        String id = param.getStringValue("id");
        String name = param.getStringValue("name");

        LambdaQueryWrapper<SysRole> lqw = new LambdaQueryWrapper<>();
        lqw.eq(StrUtil.isNotBlank(id), SysRole::getId, id);
        lqw.like(StrUtil.isNotBlank(name), SysRole::getName, name);

        Page<SysRole> page = new Page<>(pageParam.getPageNum(), pageParam.getPageSize());
        page.setOrders(MpUtil.getOrderList(orderBy));

        return baseMapper.selectPage(page, lqw);
    }

    @Override
    public void export(QueryParam param, PageParam pageParam, String orderBy, String fileDest) {

    }

    @Override
    public List<SysRole> findByUserId(Long userId) {
        return baseMapper.findByUserId(userId);
    }

    @Override
    public List<SysRole> findByAclId(Long aclId) {
        return baseMapper.findByAclId(aclId);
    }

    /**
     * 新增或修改时校验是否有同名称角色
     *
     * @param enname 角色英文名
     * @param roleId 角色ID
     * @return true含有同名角色；false不含同名角色
     */
    private boolean hasSameRole(String enname, Long roleId) {
        LambdaQueryWrapper<SysRole> lqw = new LambdaQueryWrapper<>();
        lqw.eq(SysRole::getEnname, enname);
        lqw.ne(roleId != null, SysRole::getId, roleId);
        return baseMapper.selectCount(lqw) > 0;
    }
}
